﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace AGVCallSystem
{
    public class DataSendReceive
    {
        private AsyncTcpServer server;

        private byte[] buf_return = new byte[11];

        //SortedList<TcpClient, byte[]> controlCommand = new SortedList<TcpClient, byte[]>();

        //SortedList<TcpClient, int> repeatNum = new SortedList<TcpClient, int>();

        //SortedList<TcpClient, int> delayNum = new SortedList<TcpClient, int>();

        private string ipSegment;

        public delegate void UpdateLightDelegate(string callNum);

        public UpdateLightDelegate openLightDelegate;

        public UpdateLightDelegate closeLightDelegate;

        public DataSendReceive()
        {
            TCPServerInit();
        }

        /// <summary>
        /// 服务初始化
        /// </summary>
        private void TCPServerInit()
        {
            ipSegment = ConfigurationManager.AppSettings["IPSegment"];
            string ipStr = ConfigurationManager.AppSettings["IP"];
            int port = int.Parse(ConfigurationManager.AppSettings["Port"]);
            server = new AsyncTcpServer(IPAddress.Parse(ipStr), port);
            server.ClientConnected += new EventHandler<TcpClientConnectedEventArgs>(server_ClientConnected);
            server.ClientDisconnected += new EventHandler<TcpClientDisconnectedEventArgs>(server_ClientDisconnected);
            server.DatagramReceived += new EventHandler<TcpDatagramReceivedEventArgs<byte[]>>(server_DatagramReceived);
        }

        /// <summary>
        /// 客户端连接事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void server_ClientConnected(object sender, TcpClientConnectedEventArgs e)
        {
            IPEndPoint ipEndPoint = (IPEndPoint)e.TcpClient.Client.RemoteEndPoint;
            IPAddress ipAddress = ipEndPoint.Address;
            string ipStr = ipAddress.ToString();
            int index = ipStr.LastIndexOf(".");
            string agcNumStr = ipStr.Substring(index + 1);
            byte agcNum = Convert.ToByte(agcNumStr);
        }

        /// <summary>
        /// 客户端离线事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void server_ClientDisconnected(object sender, TcpClientDisconnectedEventArgs e)
        {
            IPEndPoint ipEndPoint = (IPEndPoint)e.TcpClient.Client.RemoteEndPoint;
            IPAddress ipAddress = ipEndPoint.Address;
            string ipStr = ipAddress.ToString();
            int index = ipStr.LastIndexOf(".");
            string agcNumStr = ipStr.Substring(index + 1);
            byte agcNum = Convert.ToByte(agcNumStr);
        }

        /// <summary>
        /// 服务器接收数据事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void server_DatagramReceived(object sender, TcpDatagramReceivedEventArgs<byte[]> e)
        {
            if (e.Datagram[0] == 0xA9 && (e.Datagram[1] & 0xf0) == 0xb0
                && e.Datagram[9] == GetSUMCheck(e.Datagram, 8) && e.Datagram[10] == 0x05)
            {
                IPEndPoint ipEndPoint = (IPEndPoint)e.TcpClient.Client.RemoteEndPoint;
                IPAddress ipAddress = ipEndPoint.Address;
                string ipStr = ipAddress.ToString();
                int index = ipStr.LastIndexOf(".");
                string clientStr = ipStr.Substring(index + 1);
                byte client = Convert.ToByte(clientStr);

                ControlData_Processing(client, e.Datagram);

                //if (e.Datagram[1] == 0xb2)
                //{
                //    if (controlCommand.ContainsKey(e.TcpClient))
                //    {
                //        repeatNum.Remove(e.TcpClient);
                //        delayNum.Remove(e.TcpClient);
                //        controlCommand.Remove(e.TcpClient);
                //    }
                //}
            }
        }

        public string ServerStart()
        {
            try
            {
                TCPServerInit();
                server.Start();
                return "success";
            }
            catch (Exception ex)
            {
                return ex.Message.ToString();
            }
        }

        public string ServerStop()
        {
            try
            {
                server.Stop();
                return "success";
            }
            catch (Exception ex)
            {
                return ex.Message.ToString();
            }
        }

        /// <summary>
        /// 处理数据
        /// </summary>
        /// <param name="client">客端端（ip地址最后数据）</param>
        /// <param name="buf">收到的字节数据</param>
        private void ControlData_Processing(byte client, byte[] buf)
        {
            if (buf[1] == 0xb4)
            {
                byte callStation = client;
                byte tempCallWork = buf[3];
                byte callWork = 0;
                do
                {
                    callWork++;
                } while ((tempCallWork >>= 1) > 0);

                string callStationStr = callStation.ToString();//呼叫器站号
                string callWorkStr = callWork.ToString();//按下的按键号
                string callNum = callStationStr + "-" + callWorkStr;//组合编号
                CallDeviceBLL callDeviceBLL = new CallDeviceBLL();
                CallDeviceEntity callDeviceEntity = callDeviceBLL.GetCallDeviceByNum(callNum);//根据序号获取呼叫器按键实例

                if (callDeviceEntity != null && callDeviceEntity.EnableCall == true)
                {
                    if (buf[2] == 0x01)  //呼叫器主动发送
                    {
                        int ID = (Convert.ToInt32(buf[4]) << 24) + (Convert.ToInt32(buf[5]) << 16)
                        + (Convert.ToInt32(buf[6]) << 8) + Convert.ToInt32(buf[7]);

                        if (ID == 0)
                        {
                            if (callDeviceEntity.CallState == false)
                            {
                                callDeviceEntity.CallState = true;
                                callDeviceEntity.CallTime = DateTime.Now.ToString();
                                callDeviceBLL.EditCallDevice(callDeviceEntity);
                            }
                            ID = callDeviceEntity.Id;
                            ReplayCallDevice(ID, callNum);
                            Thread.Sleep(10);
                            SendOpenLightCommand(callNum);
                        }
                        else
                        {
                            if (callDeviceEntity.ExecuteState == false)//执行状态为off
                            {
                                callDeviceEntity.CallState = false;
                                callDeviceEntity.CallTime = "";
                                callDeviceBLL.EditCallDevice(callDeviceEntity);
                                SendCloseLightCommand(callNum);
                            }
                        }
                    }
                    else if (buf[2] == 0x02)  //呼叫器应答上位机
                    {
                        if (buf[4] == 0x00)
                        {
                            if (callDeviceEntity.CallState == false)//按键呼叫状态为off
                            {
                                callDeviceEntity.CallTime = "";
                                callDeviceEntity.LightState = false;
                                callDeviceBLL.EditCallDevice(callDeviceEntity);
                                closeLightDelegate(callNum);
                            }
                        }
                        else if (buf[4] == 0x01)
                        {
                            if (callDeviceEntity.CallState == true)//按键呼叫状态为on
                            {
                                callDeviceEntity.LightState = true;
                                callDeviceBLL.EditCallDevice(callDeviceEntity);
                                openLightDelegate(callNum);
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 响应呼叫器
        /// </summary>
        /// <param name="serialID">呼叫器编号</param>
        /// <param name="callNum">呼叫器序号</param>
        public void ReplayCallDevice(int serialID, string callNum)
        {
            string[] strArray = callNum.Split('-');
            byte stationID = Convert.ToByte(strArray[0]);
            byte lightNum = Convert.ToByte(strArray[1]);
            byte[] buf_temp = new byte[11];
            buf_temp[0] = 0xa9;
            buf_temp[1] = 0xc4;
            buf_temp[2] = 0x01;
            buf_temp[3] = (byte)(1 << (lightNum - 1));
            buf_temp[4] = Convert.ToByte((serialID & 0xff000000) >> 24);
            buf_temp[5] = Convert.ToByte((serialID & 0x00ff0000) >> 16);
            buf_temp[6] = Convert.ToByte((serialID & 0x0000ff00) >> 8);
            buf_temp[7] = Convert.ToByte((serialID & 0x000000ff));
            buf_temp[8] = 0x00;
            buf_temp[9] = GetSUMCheck(buf_temp, 8);
            buf_temp[10] = 0x05;

            string ipStr = ipSegment + stationID.ToString();
            IPAddress ipAddress = IPAddress.Parse(ipStr);
            TcpClientState tcpClientState = server.clients.Find(p =>
                ((IPEndPoint)p.tcpClient.Client.RemoteEndPoint).Address.ToString() == ipAddress.ToString());
            if (tcpClientState != null)
            {
                server.Send(tcpClientState.tcpClient, buf_temp);
            }
        }

        /// <summary>
        /// 发送亮灯命令
        /// </summary>
        /// <param name="callNum">呼叫器按键序号</param>
        public void SendOpenLightCommand(string callNum)
        {
            string[] strArray = callNum.Split('-');
            byte stationID = Convert.ToByte(strArray[0]);
            byte lightNum = Convert.ToByte(strArray[1]);
            byte[] buf_temp = new byte[11];
            buf_temp[0] = 0xa9;
            buf_temp[1] = 0xc4;
            buf_temp[2] = 0x02;
            buf_temp[3] = (byte)(1 << (lightNum - 1));
            buf_temp[4] = 0x01;
            buf_temp[5] = 0x00;
            buf_temp[6] = 0x00;
            buf_temp[7] = 0x00;
            buf_temp[8] = 0x00;
            buf_temp[9] = GetSUMCheck(buf_temp, 8);
            buf_temp[10] = 0x05;

            string ipStr = ipSegment + stationID.ToString();
            IPAddress ipAddress = IPAddress.Parse(ipStr);
            TcpClientState tcpClientState = server.clients.Find(p =>
                ((IPEndPoint)p.tcpClient.Client.RemoteEndPoint).Address.ToString() == ipAddress.ToString());
            if (tcpClientState != null)
            {
                server.Send(tcpClientState.tcpClient, buf_temp);
            }
        }

        /// <summary>
        /// 发送灭灯指令
        /// </summary>
        /// <param name="callNum">呼叫器按键号</param>
        public void SendCloseLightCommand(string callNum)
        {
            string[] strArray = callNum.Split('-');
            byte stationID = Convert.ToByte(strArray[0]);
            byte lightNum = Convert.ToByte(strArray[1]);
            byte[] buf_temp = new byte[11];
            buf_temp[0] = 0xa9;
            buf_temp[1] = 0xc4;
            buf_temp[2] = 0x02;
            buf_temp[3] = (byte)(1 << (lightNum - 1));
            buf_temp[4] = 0x00;
            buf_temp[5] = 0x00;
            buf_temp[6] = 0x00;
            buf_temp[7] = 0x00;
            buf_temp[8] = 0x00;
            buf_temp[9] = GetSUMCheck(buf_temp, 8);
            buf_temp[10] = 0x05;

            string ipStr = ipSegment + stationID.ToString();
            IPAddress ipAddress = IPAddress.Parse(ipStr);
            TcpClientState tcpClientState = server.clients.Find(p =>
                ((IPEndPoint)p.tcpClient.Client.RemoteEndPoint).Address.ToString() == ipAddress.ToString());
            if (tcpClientState != null)
            {
                server.Send(tcpClientState.tcpClient, buf_temp);
            }
        }

        /// <summary>
        /// 获取和校验
        /// </summary>
        /// <param name="bufCode">字节数组</param>
        /// <param name="bufLen">长度</param>
        /// <returns></returns>
        private byte GetSUMCheck(byte[] bufCode, int bufLen)
        {
            int temp = 0;
            byte sumCheck = 0;
            for (int i = 0; i < bufLen; i++)
            {
                temp += bufCode[i + 1];
            }
            sumCheck = Convert.ToByte(temp & 0x000000ff);
            return sumCheck;
        }
    }
}
